#ifndef _SPI_NOR_CMD_H_
#define	_SPI_NOR_CMD_H_

#include "stdint.h"

//SPI NOR包含3个安全寄存器页，操作同主存储器页，只是指令不同。 三页的写保护由状态寄存器的LB位指定，LB位是OPT位；
//三页起始地址 0x001000, 0x002000, 0x003000。每页1KB容量。建议只使用前256字节，因为与其兼容的其他厂家有些IC的页尺寸为256.
//状态寄存器的LB位是0时，安全寄存器区可随意读写，LB设为1后，LB及安全寄存器被写保护，永远不可再次操作。

//The Write Status Register (WRSR) command has no effect on S23, S20, S19, S18, S17, S16, S15, S10, S1 and S0

//statue cfg POS define， 以下配置位均为非易失配置位，配置一次即可。 其中LB为OPT，SRP在部分芯片上可令整个status所有配置位变为OPT
#define SPI_NOR_ST_DRV_POS								21		//drv 2bits, 指示管脚驱动能力
#define SPI_NOR_ST_QE_POS								9		//指示QPI管脚是否使能 
#define SPI_NOR_ST_LB_POS								11		//LB 3bits, 安全寄存器写保护位，OPT
#define SPI_NOR_ST_ADDR_MODE_POS						8		//当前地址模式

// statue define
#define SPI_NOR_ST_BUSY_MASK							0x01
#define SPI_NOR_ST_WRITE_EN								0x02	


/*****************************************************************************
* @brief   CMD LIST - SAME AT ADDR-24 AND ADDR-32
*****************************************************************************/
#define SPI_NOR_CMD_Write_Enable						0x06
#define SPI_NOR_CMD_Write_Disable						0x04
#define SPI_NOR_CMD_SRWrite_Enable						0x50

#define SPI_NOR_CMD_Read_StReg1							0x05
#define SPI_NOR_CMD_Read_StReg2							0x35
#define SPI_NOR_CMD_Read_StReg3							0x15
#define SPI_NOR_CMD_Write_StReg1						0x01
#define SPI_NOR_CMD_Write_StReg2						0x31
#define SPI_NOR_CMD_Write_StReg3						0x11

#define SPI_NOR_CMD_Chip_Erase							0x60
#define SPI_NOR_CMD_Enable_Reset						0x66
#define SPI_NOR_CMD_Reset								0x99

#define SPI_NOR_CMD_Read_Identification					0x9F // 各厂商指令格式不同
#define SPI_NOR_CMD_Read_Device_ID						0x90 //

/*****************************************************************************
* @brief   CMD LIST - DIFF AT ADDR-24 AND ADDR-32
*****************************************************************************/
#define SPI_NOR_CMD_Read_Data							0x03 //SPI 读
#define SPI_NOR_CMD_Fast_Read							0x0B //SPI 读

#define SPI_NOR_CMD_Quad_Read							0x6B //CMD-A-SPI，D-QSPI
#define SPI_NOR_CMD_Quad_Read_QA						0xEB //CMD-SPI，A-D-QSPI

#define SPI_NOR_CMD_Page_Program						0x02 //SPI 写
#define SPI_NOR_CMD_Quad_Page_Program					0x32 //CMD-A-SPI，D-QSPI

#define SPI_NOR_CMD_Sector_Erase						0x20
#define SPI_NOR_CMD_Block_Erase_32K						0x52
#define SPI_NOR_CMD_Block_Erase_64K						0xD8

#define SPI_NOR_CMD_Erase_SecurityReg					0x44
#define SPI_NOR_CMD_Program_SecurityReg					0x42
#define SPI_NOR_CMD_Read_SecurityReg					0x48


/*****************************************************************************
* @brief   CMD LIST - FOR ADDR-32
*****************************************************************************/
#define SPI_NOR_CMD_A32_Enter_A32						0xB7
#define SPI_NOR_CMD_A32_Exit_A32						0xE9
#define SPI_NOR_CMD_A32_Set_Addr_MB						0xC5
#define SPI_NOR_CMD_A32_Get_Addr_MB						0xC8

#define SPI_NOR_CMD_A32_Sector_Erase					0x21
#define SPI_NOR_CMD_A32_Block_Erase_32K					0x5C
#define SPI_NOR_CMD_A32_Block_Erase_64K					0xDC

#define SPI_NOR_CMD_A32_Read_Data						0x13 //SPI 读
#define SPI_NOR_CMD_A32_Fast_Read						0x0C //SPI 读
#define SPI_NOR_CMD_A32_Page_Program					0x12 //SPI 写

#define SPI_NOR_CMD_A32_Quad_Read						0x6C //CMD-A-SPI，D-QSPI
#define SPI_NOR_CMD_A32_Quad_Read_QA					0xEC //CMD-SPI，A-D-QSPI
#define SPI_NOR_CMD_A32_Quad_Page_Program				0x34 //CMD-A-SPI，D-QSPI

/*****************************************************************************
* @brief   FLASH INFO
*****************************************************************************/
#define SPI_NOR_PAGE_SIZE								0x100
#define SPI_NOR_PAGE_MASK								0xFF
#define SPI_NOR_SECTOR_SIZE								0x1000
#define SPI_NOR_BLOCK32_SIZE							0x8000
#define SPI_NOR_BLOCK64_SIZE							0x10000
#define SPI_NOR_PLANE_SIZE								0x1000000

/*****************************************************************************
* @brief   CONTROL STRUCT
*****************************************************************************/
typedef enum
{
	SPI_NOR_SPI_MODE = 0,
	SPI_NOR_QPI_READ_MODE,
	SPI_NOR_QPI_WRITE_MODE,
} nor_spi_type;

typedef struct
{
	//* extern api
	void(*cs)(uint8_t st);
	void(*spi_mode)(nor_spi_type mode);
	uint8_t(*spi_rw)(uint8_t dataW);
	uint8_t(*spi_cmd_send)(const uint8_t *dataw, uint8_t Len);
	uint8_t(*qpi_cmd_send)(const uint8_t *dataw, uint8_t Len);
	uint8_t(*spi_write)(const uint8_t *dataw, uint32_t Len);
	uint8_t(*spi_read)(uint8_t *datar, uint32_t Len);
	uint8_t(*qpi_write)(const uint8_t *dataw, uint32_t Len);
	uint8_t(*qpi_read)(uint8_t *datar, uint32_t Len);
} multi_nor_type;


/*****************************************************************************
* @brief   MULTI NOR-FLASH API
*****************************************************************************/
uint32_t multi_nor_init(const multi_nor_type *hal, uint8_t qspi_en);

// 寄存器操作 1 2 3
uint8_t multi_nor_reg_get(const multi_nor_type *hal, char reg);
uint8_t multi_nor_reg_set(const multi_nor_type *hal, char reg, uint8_t msk, uint8_t val); // return reg-val now

// 状态
uint32_t multi_nor_st_read(const multi_nor_type *hal);		// st read = reg1 + reg2 + reg3
uint8_t multi_nor_busy(const multi_nor_type *hal);			// get busy st
uint8_t multi_nor_wait_for_busy(const multi_nor_type *hal);	// return 1 is ok, 0 is error.

// ID
uint8_t multi_nor_id_read(const multi_nor_type *hal, uint8_t *des);

// 写使能
void multi_nor_write_enable(const multi_nor_type *hal);
void multi_nor_write_disable(const multi_nor_type *hal);

// 擦除
uint8_t multi_nor_sector_erase(const multi_nor_type *hal, uint32_t addr);
uint8_t multi_nor_block_erase(const multi_nor_type *hal, uint32_t addr);
uint8_t multi_nor_block64_erase(const multi_nor_type *hal, uint32_t addr);
uint8_t multi_nor_chip_erase(const multi_nor_type *hal);

// SPI 读写
uint8_t multi_nor_read(const multi_nor_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);		//CMD-03H
uint8_t multi_nor_write(const multi_nor_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);	//CMD-02H
uint8_t multi_nor_write_multi(const multi_nor_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);

// QPI 读写
uint8_t multi_nor_q_read(const multi_nor_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);	//CMD-6BH
uint8_t multi_nor_qa_read(const multi_nor_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);	//CMD-EBH
uint8_t multi_nor_q_write(const multi_nor_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);  //CMD-32H
uint8_t multi_nor_q_write_multi(const multi_nor_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);

// 附加安全区
uint8_t multi_nor_security_reg_read(const multi_nor_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);
uint8_t multi_nor_security_reg_write(const multi_nor_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);
uint8_t multi_nor_security_reg_erase(const multi_nor_type *hal, uint32_t addr);

// 单字节命令
void multi_nor_cmd_signal_exe(const multi_nor_type *hal, uint8_t cmd);
uint8_t multi_nor_cmd_exe(const multi_nor_type *hal, uint8_t cmd, uint8_t par);

// 自定义命令，内部执行等待busy
uint8_t multi_nor_cmd_auto(const multi_nor_type *hal, const uint8_t *send, uint8_t send_len, uint8_t *rcv, uint8_t rcv_cnt);

// A32 基本命令
uint8_t multi_nor32_enter_a32_mode(const multi_nor_type *hal);
uint8_t multi_nor32_enter_a24_mode(const multi_nor_type *hal);
uint8_t multi_nor32_addr_mb_set(const multi_nor_type *hal, uint8_t mb);
uint8_t multi_nor32_addr_mb_get(const multi_nor_type *hal);

uint8_t multi_nor32_sector_erase(const multi_nor_type *hal, uint32_t addr);
uint8_t multi_nor32_block_erase(const multi_nor_type *hal, uint32_t addr);
uint8_t multi_nor32_block64_erase(const multi_nor_type *hal, uint32_t addr);

// A32 SPI 读写
uint8_t multi_nor32_read(const multi_nor_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);		//CMD-13H
uint8_t multi_nor32_write(const multi_nor_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);		//CMD-12H
uint8_t multi_nor32_write_multi(const multi_nor_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);

// A32 QPI 读写
uint8_t multi_nor32_q_read(const multi_nor_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);	//CMD-6CH
uint8_t multi_nor32_qa_read(const multi_nor_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);	//CMD-ECH
uint8_t multi_nor32_q_write(const multi_nor_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);	//CMD-34H
uint8_t multi_nor32_q_write_multi(const multi_nor_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);

/*****************************************************************************
* @brief   SIGNAL NOR-FLASH API
*****************************************************************************/
uint32_t nor_init(uint8_t qspi_en);

// 寄存器操作 1 2 3
uint8_t nor_reg_get(char reg);
uint8_t nor_reg_set(char reg, uint8_t msk, uint8_t val);

// 状态
uint32_t nor_st_read(void);			// st read = reg1 + reg2 + reg3
uint8_t  nor_busy(void);			// get busy st, reg1.b0
uint8_t nor_wait_for_busy(void);	// return 1 is ok, 0 is error.

// ID
uint8_t  nor_id_read(uint8_t *des);

// 写使能
void nor_write_enable(void);
void nor_write_disable(void);

// 擦除
uint8_t nor_sector_erase(uint32_t addr);
uint8_t nor_block_erase(uint32_t addr);
uint8_t nor_block64_erase(uint32_t addr);
uint8_t nor_chip_erase(void );

// SPI 读写
uint8_t nor_read(uint32_t addr,int32_t Len,uint8_t *Des);
uint8_t nor_write(uint32_t addr,int32_t Len,const uint8_t *Src);
uint8_t nor_write_multi(uint32_t addr, int32_t Len, const uint8_t *Src); // 内部分页

// QPI 读写
uint8_t nor_q_read(uint32_t addr,int32_t Len,uint8_t *Des);		// CMD-6B
uint8_t nor_qa_read(uint32_t addr, int32_t Len, uint8_t *Des);		// CMD-EB
uint8_t nor_q_write(uint32_t addr,int32_t Len, const uint8_t *Src); 		//部分芯片QPI写入要求较低的时钟频率
uint8_t nor_q_write_multi(uint32_t addr, int32_t Len, const uint8_t *Src); // 内部分页

// 附加安全区
uint8_t nor_security_reg_read(uint32_t addr, int32_t Len, uint8_t *Des);
uint8_t nor_security_reg_write(uint32_t addr, int32_t Len, const uint8_t *Src);
uint8_t nor_security_reg_erase(uint32_t addr);

// 单字节命令
void nor_cmd_signal_exe (uint8_t cmd);
uint8_t nor_cmd_exe (uint8_t cmd, uint8_t par);
uint8_t nor_cmd_auto(const uint8_t *send, uint8_t send_len, uint8_t *rcv, uint8_t rcv_cnt);

// A32 基本命令
uint8_t nor32_enter_a32_mode(void);
uint8_t nor32_enter_a24_mode(void);
uint8_t nor32_addr_mb_set(uint8_t mb);
uint8_t nor32_addr_mb_get(void);

uint8_t nor32_sector_erase(uint32_t addr);
uint8_t nor32_block_erase(uint32_t addr);
uint8_t nor32_block64_erase(uint32_t addr);

// A32 SPI 读写
uint8_t nor32_read(uint32_t addr, int32_t Len, uint8_t *Des);		//CMD-13H
uint8_t nor32_write(uint32_t addr, int32_t Len, const uint8_t *Src);		//CMD-12H
uint8_t nor32_write_multi(uint32_t addr, int32_t Len, const uint8_t *Src);

// A32 QPI 读写
uint8_t nor32_q_read(uint32_t addr, int32_t Len, uint8_t *Des);		//CMD-6CH
uint8_t nor32_qa_read(uint32_t addr, int32_t Len, uint8_t *Des);	//CMD-ECH
uint8_t nor32_q_write(uint32_t addr, int32_t Len, const uint8_t *Src);	//CMD-34H
uint8_t nor32_q_write_multi(uint32_t addr, int32_t Len, const uint8_t *Src);


#endif	/* _SPI_NOR_CMD_H_ */

